package com.thinkit.security.login;
import com.thinkit.nosql.base.BaseRedisService;
import com.thinkit.utils.enums.UserFrom;
import com.thinkit.utils.utils.SpringContextHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;

import java.lang.reflect.Constructor;

@Component
public class VerificationExecutor {

    @Autowired
    BCryptPasswordEncoder bCryptPasswordEncoder;

    public UserDetails verify(String userAccount, String userPassword, UserFrom userFrom) throws Exception {
        LoginChecker loginChecker =loginChecker(userFrom,userAccount,userPassword);
        UserDetails userDetails= null;
        try {
            userDetails = loginChecker.login();
        }catch (Exception e){
            loginChecker.loginFail(userDetails,userAccount);
            throw e;
        }
        loginChecker.loginSuccess(userDetails,userAccount);
        return userDetails;
    }

    private LoginChecker loginChecker( UserFrom userFrom,String userAccount, String userPassword){
        Class clz = null;
        try {
            clz = Class.forName(userFrom.getLoginCheckPck());
            LoginChecker loginChecker = initLoginChecker(userAccount,userPassword,userFrom.getClientId(),clz).
            build(getUserDetailService(userFrom.getUserService()),bCryptPasswordEncoder,getRedisService());
            return loginChecker;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    private UserDetailsService getUserDetailService(String serviceName){
       return  SpringContextHolder.getBean(serviceName);
    }

    private BaseRedisService getRedisService(){
       return SpringContextHolder.getBean(BaseRedisService.class);
    }

    private LoginChecker initLoginChecker(String userAccount, String userPassword,String clientId,Class<? extends LoginChecker> loginChecker){
        try {
            Constructor constructor=loginChecker.getConstructor(String.class,String.class,String.class);
            return (LoginChecker) constructor.newInstance(userAccount,userPassword,clientId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}
